package com.zyl.unsafe;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhaoyl
 * @date 2024/5/15 22:02
 * @description 说明
 * Map多线程安全问题
 */
//.ConcurrentModificationException
public class MapTest {
    public static void main(String[] args) {
        //默认new HashMap<>(16,0.75);初始化，加载因子;多线程不安全
       // Map<String,String> map = new HashMap<>();

        /*
        解决方法1
        Collections.synchronizedMap 同步锁
        * */
       //  Map<String,String> map = Collections.synchronizedMap(new HashMap<>());

        /*
        解决方法2
        ConcurrentHashMap 分段锁或
        * */
        Map<String,String> map =new ConcurrentHashMap<>();


        for (int i=1;i<=20;i++){
            new Thread(()->{
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5));
                System.out.println(map);
            },String.valueOf(i)).start();;
        }
    }
}
/*
* 1、Collections.synchronizedMap() : 这是一个静态工厂方法，它接收一个现有的 Map 实例作为参数，
* 并返回一个经过包装的线程安全的 Map。使用一个全局的锁来确保线程安全，无论是读取还是写入操作都会获取这把锁，
* 这意味着所有的操作都是互斥的，即在同一时刻只能有一个线程进行操作，因此不能说它是原子级别的操作，
* 除非操作本身就是原子性的（例如，简单的 get 或 put 操作针对的是单个对象引用）。在高并发环境下，
* 当多个线程同时访问不同的键值对时，可能会导致性能瓶颈。

2、ConcurrentHashMap :采用了一种粒度更细的锁机制（通常称为分段锁或者分区锁），
* 将内部的数据结构划分为多个部分或桶（bucket），每个桶都可以独立地加锁和解锁，从而实现了更高的并发性能。
* 在大多数情况下，多个线程可以同时对不同键进行读写操作，而不会相互阻塞，除非它们碰巧要修改同一个桶内的数据。
* ConcurrentHashMap 还提供了额外的原子操作方法，比如 putIfAbsent, remove, replace, computeIfAbsent, computeIfPresent 等

底层实现不同
1、Collections.synchronizedMap 是使用一个包装器类来实现的。
2、ConcurrentHashMap 是使用数组+链表来实现的。
* */
